#ifndef HAVE_TEXT2XML_LEXER_H
#define HAVE_TEXT2XML_LEXER_H

#include <glib.h>
#include "Token.h"
#include "Lexicon.h"
#include "Node.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _Lexer {
  const char* input;
  long        input_length;
  long        current_char;
  long        current_line;
  GList*      token_buffer;
  GList*      lexicons;
} Lexer;

/**
 * Returns a new lexer.
 */
Lexer* lexer_new(void);

/**
 * Destroys the lexer.
 */
void lexer_free(Lexer* lexer);

/**
 * Defines the string that is parsed.
 */
void lexer_set_input(Lexer* lexer, const char* input);

/**
 * Returns 1 if the lexer has completed, 0 otherwise.
 */
short int lexer_is_done(Lexer* lexer);

/**
 * Defines the lexicon used in the lexer by pushing it on
 * a lexicon stack.
 */
void lexer_push_lexicon(Lexer* lexer, Lexicon* lexicon);

/**
 * Removes the top of the lexicon stack.
 */
void lexer_pop_lexicon(Lexer* lexer);

/**
 * Returns the current token.
 */
Token* lexer_get_token(Lexer* lexer);

/**
 * Parses the next token and returns the list of tokens if it matches 
 * the given token. Returns NULL otherwise.
 */
short int lexer_next_if(Lexer* lexer, Token* token);

/**
 * Parses the next few tokens and returns the list of tokens if they
 * match the given regular expressions. Returns NULL otherwise.
 * This function ignores the lexicon and only uses the given expressions 
 * to perform the matching.
 * Any memory returned by this function must be freed by the client.
 */
Vector* lexer_next_if_re_list(Lexer* lexer, GList* re_list);

/**
 * Throws an error if the current token does not match the given
 * token. Parses the next token otherwise.
 */
void lexer_expect(Node* sender, Lexer* lexer, Token* token);

/**
 * Returns True if the current token matches the given token,
 * returns False otherwise.
 */
short int lexer_current_is(Lexer* lexer, Token* token);

#ifdef __cplusplus
}
#endif                          /* __cplusplus */
#endif                          /* HAVE_TEXT2XML_LEXER_H */
